package com.blue.rpc.server;

import java.util.List;
import java.util.Set;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.core.task.TaskExecutor;

import com.blue.core.file.ClassScanner;
import com.blue.core.util.NetworkUtil;
import com.blue.rpc.core.annotation.RpcClassHandler;
import com.blue.rpc.core.annotation.RpcParser;
import com.blue.rpc.core.codec.MessageProtostuffDecoder;
import com.blue.rpc.core.codec.MessageProtostuffEncoder;
import com.blue.rpc.core.message.RpcRequest;
import com.blue.rpc.core.registry.Registry;

import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.LengthFieldBasedFrameDecoder;

/**
 * RPC初始化类
 * 
 * @author zhengj
 * @since 1.0 2017年3月13日
 */
public class RpcServerInitializer extends ChannelInitializer<SocketChannel>
		implements InitializingBean, ApplicationContextAware
{
	private static Logger logger = LoggerFactory.getLogger(RpcServerInitializer.class);

	private TaskExecutor taskExecutor;
	private List<String> packageList;
	private RpcParser parser;
	private Registry registry;
	private String token;

	public RpcServerInitializer()
	{
	}

	@Override
	protected void initChannel(SocketChannel ch) throws Exception
	{
		ChannelPipeline cp = ch.pipeline();

		// 获取完整数据包
		cp.addLast(new LengthFieldBasedFrameDecoder(Integer.MAX_VALUE, 0, 4, 0, 0));

		// 编码/解码器
		// cp.addLast(new MessageJsonDecoder(RpcRequest.class));
		// cp.addLast(new MessageJsonEncoder());
		cp.addLast(new MessageProtostuffDecoder(RpcRequest.class));
		cp.addLast(new MessageProtostuffEncoder());

		// 心跳处理器
		cp.addLast(new HeartbeatHandler());

		// 业务处理器
		cp.addLast(new RpcServerHandler(taskExecutor, parser, token));
	}

	public void registerInterface(int port)
	{
		if (registry == null)
			return;

		Set<Class<?>> interfaceSet = parser.getAllInterface();
		List<String> addrList = NetworkUtil.getLocalAddress();
		for (String addr : addrList)
		{
			for (Class<?> interfaceClass : interfaceSet)
			{
				String interfaceName = interfaceClass.getName();
				registry.registerInterface(interfaceName, addr, port);
			}
		}
	}

	public void setRegistry(Registry registry)
	{
		this.registry = registry;
	}

	public void setTaskExecutor(TaskExecutor taskExecutor)
	{
		this.taskExecutor = taskExecutor;
	}

	public void setScanPackages(List<String> packageList)
	{
		this.packageList = packageList;
	}

	public void setToken(String token)
	{
		this.token = token;
	}

	@Override
	public void setApplicationContext(ApplicationContext applicationContext)
			throws BeansException
	{
		this.parser = new RpcParser(applicationContext);
	}

	@Override
	public void afterPropertiesSet() throws Exception
	{
		logger.info("扫描包：{}", packageList);
		ClassScanner scanner = new ClassScanner();
		scanner.setClassHandler(new RpcClassHandler(parser));
		scanner.scan(packageList);
	}

}
